package com.agritech;

import com.agritech.adapter.AdvancedDrone;
import com.agritech.adapter.DroneAdapter;
import com.agritech.chain.*;
import com.agritech.command.RemoteControl;
import com.agritech.command.StartMachineCommand;
import com.agritech.command.StopMachineCommand;
import com.agritech.environment.EnvironmentData;
import com.agritech.environment.EnvironmentMonitoringSystem;
import com.agritech.facade.ControlPanelFacade;
import com.agritech.factory.*;
import com.agritech.machine.*;
import com.agritech.observer.EnvironmentObserver;
import com.agritech.path.PathPlan;
import com.agritech.path.PathPlanningContext;
import com.agritech.strategy.AStarPathStrategy;
import com.agritech.strategy.EnergyEfficientPathStrategy;
import com.agritech.strategy.ShortestPathStrategy;
import com.agritech.system.NavigationSystem;
import com.agritech.task.Task;
import com.agritech.task.TaskScheduler;
import com.agritech.adapter.ThirdPartyDrone; // Added to fix compilation error
import com.agritech.observer.TractorObserver; // Added to fix compilation error

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class MainApp {

    public static void main(String[] args) {
        System.out.println("欢迎来到智能无人驾驶农机系统!");

        // 1. 初始化环境监测系统 (观察者模式 - 主题)
        EnvironmentMonitoringSystem envMonitor = new EnvironmentMonitoringSystem();

        // 2. 创建农机 (工厂方法模式)
        MachineFactory seederFactory = new SeederFactory();
        AgriculturalMachine seeder = seederFactory.createMachine("SDR-001");

        MachineFactory harvesterFactory = new HarvesterFactory();
        AgriculturalMachine harvester = harvesterFactory.createMachine("HRV-002");

        MachineFactory sprayerFactory = new SprayerFactory();
        AgriculturalMachine sprayer = sprayerFactory.createMachine("SPY-003");
        
        MachineFactory tractorFactory = new TractorFactory();
        AgriculturalMachine tractor = tractorFactory.createMachine("TRC-004");

        // 3. 创建第三方无人机和适配器 (适配器模式)
        AdvancedDrone advancedDrone = new AdvancedDrone("DJI-PhantomX");
        DroneAdapter droneAdapter = new DroneAdapter(advancedDrone, "DRN-005", "DJI-PhantomX");

        // 将所有农机（包括适配器）放入列表
        List<AgriculturalMachine> allMachines = new ArrayList<>(Arrays.asList(seeder, harvester, sprayer, tractor, droneAdapter));

        // 4. 注册观察者 (观察者模式 - 观察者)
        // 为每个农机创建对应的观察者并注册到环境监测系统
        if (seeder instanceof Seeder) envMonitor.registerObserver(new SeederObserver((Seeder)seeder));
        if (harvester instanceof Harvester) envMonitor.registerObserver(new HarvesterObserver((Harvester)harvester));
        if (sprayer instanceof Sprayer) envMonitor.registerObserver(new SprayerObserver((Sprayer)sprayer));
        // Tractor 类需要实现 EnvironmentObserver 接口才能直接注册，或者通过一个TractorObserver类
        // 假设 Tractor 自身实现了 EnvironmentObserver (在Tractor.java中添加 implements EnvironmentObserver 和 update方法)
        // if (tractor instanceof Tractor) envMonitor.registerObserver((EnvironmentObserver)tractor); 
        // 或者创建一个TractorObserver类，如下：
        if (tractor instanceof Tractor) envMonitor.registerObserver(new TractorObserver((Tractor)tractor));
        envMonitor.registerObserver(droneAdapter); // DroneAdapter 实现了 EnvironmentObserver
        
        // 5. 初始化控制面板外观 (外观模式)
        ControlPanelFacade controlPanel = new ControlPanelFacade(allMachines, envMonitor);

        // 6. 初始化责任链 (责任链模式)
        ExceptionHandler lowFuelHandler = new LowFuelExceptionHandler();
        ExceptionHandler sensorFailureHandler = new SensorFailureExceptionHandler();
        ExceptionHandler commLossHandler = new CommunicationLossExceptionHandler();
        ExceptionHandler unknownHandler = new UnknownExceptionHandler();

        lowFuelHandler.setNextHandler(sensorFailureHandler);
        sensorFailureHandler.setNextHandler(commLossHandler);
        commLossHandler.setNextHandler(unknownHandler);
        // 模拟异常发生
        System.out.println("\n--- 责任链模式演示 ---");
        lowFuelHandler.handleRequest("农机 SDR-001 低燃油警告");
        lowFuelHandler.handleRequest("农机 HRV-002 传感器故障: 湿度传感器无响应");
        lowFuelHandler.handleRequest("农机 SPY-003 GPS信号丢失，通信中断");
        lowFuelHandler.handleRequest("农机 TRC-004 发生未知错误代码 E-1024");
        System.out.println("---------------------");

        // 7. 演示单例导航系统 (单例模式)
        System.out.println("\n--- 单例模式演示 (导航系统) ---");
        NavigationSystem navSys1 = NavigationSystem.getInstance();
        NavigationSystem navSys2 = NavigationSystem.getInstance();
        System.out.println("导航系统实例1哈希码: " + navSys1.hashCode());
        System.out.println("导航系统实例2哈希码: " + navSys2.hashCode());
        System.out.println("两个实例是否相同: " + (navSys1 == navSys2));
        navSys1.updateMap("v1.1.0-release");
        System.out.println("实例2获取的地图版本: " + navSys2.getCurrentMapVersion());
        System.out.println("---------------------");

        // 启动交互式控制面板
        runInteractiveMode(controlPanel);

        System.out.println("\n感谢使用智能无人驾驶农机系统，系统退出。");
    }

    private static void runInteractiveMode(ControlPanelFacade controlPanel) {
        Scanner scanner = new Scanner(System.in);
        boolean exit = false;

        while (!exit) {
            System.out.println("\n--- 智能农机交互式控制面板 ---");
            System.out.println("1. 环境监测");
            System.out.println("2. 农机管理");
            System.out.println("3. 任务调度");
            System.out.println("4. 路径规划与导航");
            System.out.println("5. 命令控制 (演示撤销)");
            System.out.println("6. 退出系统");
            System.out.print("请输入操作选项 (1-6): ");

            if (!scanner.hasNextInt()) {
                System.out.println("无效输入，请输入数字。");
                scanner.next(); // 清除无效输入
                continue;
            }
            int choice = scanner.nextInt();
            scanner.nextLine(); // 消耗换行符

            switch (choice) {
                case 1:
                    controlPanel.collectAndDisplayEnvironmentData();
                    break;
                case 2:
                    manageMachines(scanner, controlPanel);
                    break;
                case 3:
                    manageTasks(scanner, controlPanel);
                    break;
                case 4:
                    managePathPlanning(scanner, controlPanel);
                    break;
                case 5:
                    demoCommandPattern(scanner, controlPanel);
                    break;
                case 6:
                    exit = true;
                    break;
                default:
                    System.out.println("无效选项，请重新输入。");
            }
        }
        scanner.close();
    }

    private static void manageMachines(Scanner scanner, ControlPanelFacade controlPanel) {
        boolean back = false;
        while (!back) {
            System.out.println("\n  --- 农机管理 ---");
            System.out.println("  1. 查看所有农机状态");
            System.out.println("  2. 启动农机");
            System.out.println("  3. 停止农机");
            System.out.println("  4. 维修农机 (状态模式演示)");
            System.out.println("  5. 返回主菜单");
            System.out.print("  请输入操作选项 (1-5): ");
            if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); continue; }
            int choice = scanner.nextInt();
            scanner.nextLine(); 

            String machineId;
            AgriculturalMachine machine;
            switch (choice) {
                case 1:
                    controlPanel.displayAllMachineStatus();
                    break;
                case 2:
                    System.out.print("  请输入要启动的农机ID: ");
                    machineId = scanner.nextLine();
                    controlPanel.startMachine(machineId);
                    break;
                case 3:
                    System.out.print("  请输入要停止的农机ID: ");
                    machineId = scanner.nextLine();
                    controlPanel.stopMachine(machineId);
                    break;
                case 4: // 状态模式演示
                    System.out.print("  请输入要操作的农机ID (演示状态变化): ");
                    machineId = scanner.nextLine();
                    machine = controlPanel.findMachineById(machineId);
                    if (machine != null) {
                        System.out.println("    当前农机 "+machine.getId()+" 状态: " + machine.getStatus());
                        System.out.println("    1. 启动 -> 工作中");
                        System.out.println("    2. 执行任务 (可能因燃油不足变故障)");
                        System.out.println("    3. 停止 -> 空闲");
                        System.out.println("    4. 维修 -> 空闲 (修好并加油)");
                        System.out.println("    5. (模拟)强制进入故障状态");
                        System.out.print("    请选择操作: ");
                        if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); continue; }
                        int stateChoice = scanner.nextInt(); scanner.nextLine();
                        switch(stateChoice) {
                            case 1: machine.start(); break;
                            case 2: machine.performTask("演示状态任务"); break;
                            case 3: machine.stop(); break;
                            case 4: machine.repair(); break;
                            case 5: machine.getStateContext().setState(new com.agritech.state.BrokenState("手动模拟故障")); break;
                            default: System.out.println("无效状态操作");
                        }
                        System.out.println("    操作后农机 "+machine.getId()+" 状态: " + machine.getStatus());
                    } else {
                        System.out.println("  未找到农机 " + machineId);
                    }
                    break;
                case 5:
                    back = true;
                    break;
                default:
                    System.out.println("  无效选项。");
            }
        }
    }

    private static void manageTasks(Scanner scanner, ControlPanelFacade controlPanel) {
        boolean back = false;
        while (!back) {
            System.out.println("\n  --- 任务调度 ---");
            System.out.println("  1. 创建新任务");
            System.out.println("  2. 分配任务给农机");
            System.out.println("  3. 自动分配任务");
            System.out.println("  4. 启动任务");
            System.out.println("  5. 完成任务");
            System.out.println("  6. 取消任务");
            System.out.println("  7. 查看所有任务状态");
            System.out.println("  8. 查看任务详情");
            System.out.println("  9. 返回主菜单");
            System.out.print("  请输入操作选项 (1-9): ");
            if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); continue; }
            int choice = scanner.nextInt();
            scanner.nextLine(); 
            
            String taskId, machineId, taskName, taskDesc;
            double duration;
            Task task;
            switch (choice) {
                case 1:
                    System.out.print("  请输入任务名称: "); taskName = scanner.nextLine();
                    System.out.print("  请输入任务描述: "); taskDesc = scanner.nextLine();
                    System.out.print("  请输入预计时长(小时): "); duration = scanner.nextDouble(); scanner.nextLine();
                    controlPanel.createTask(taskName, taskDesc, duration);
                    break;
                case 2:
                    controlPanel.getTaskScheduler().printAllTaskStatuses();
                    System.out.print("  请输入要分配的任务ID: "); taskId = scanner.nextLine();
                    task = findTask(taskId, controlPanel);
                    if (task == null) { System.out.println("未找到任务 " + taskId); break; }
                    controlPanel.displayAllMachineStatus();
                    System.out.print("  请输入要分配到的农机ID: "); machineId = scanner.nextLine();
                    // 路径规划可以后续添加或在此处简化
                    controlPanel.assignTaskToMachine(task, machineId, null);
                    break;
                case 3:
                    controlPanel.autoAssignTasks();
                    break;
                case 4:
                    controlPanel.getTaskScheduler().printAllTaskStatuses();
                    System.out.print("  请输入要启动的任务ID: "); taskId = scanner.nextLine();
                    controlPanel.startScheduledTask(taskId);
                    break;
                case 5:
                    controlPanel.getTaskScheduler().printAllTaskStatuses();
                    System.out.print("  请输入要完成的任务ID: "); taskId = scanner.nextLine();
                    controlPanel.completeScheduledTask(taskId);
                    break;
                case 6:
                    controlPanel.getTaskScheduler().printAllTaskStatuses();
                    System.out.print("  请输入要取消的任务ID: "); taskId = scanner.nextLine();
                    controlPanel.cancelScheduledTask(taskId);
                    break;
                case 7:
                    controlPanel.displayAllTaskStatuses();
                    break;
                case 8:
                    System.out.print("  请输入要查看详情的任务ID: "); taskId = scanner.nextLine();
                    controlPanel.displayTaskDetails(taskId);
                    break;
                case 9:
                    back = true;
                    break;
                default:
                    System.out.println("  无效选项。");
            }
        }
    }
    
    private static Task findTask(String taskId, ControlPanelFacade controlPanel) {
        Task task = controlPanel.getTaskScheduler().getActiveTasks().get(taskId);
        if (task == null) {
            task = controlPanel.getTaskScheduler().getTaskQueue().stream()
                .filter(t -> t.getTaskId().equals(taskId)).findFirst().orElse(null);
        }
        return task;
    }

    private static void managePathPlanning(Scanner scanner, ControlPanelFacade controlPanel) {
        boolean back = false;
        while (!back) {
            System.out.println("\n  --- 路径规划与导航 ---");
            System.out.println("  1. 设置路径规划策略 (当前: " + controlPanel.getPathPlanner().getStrategy().getStrategyName() + ")");
            System.out.println("  2. 为农机规划路径");
            System.out.println("  3. 启动导航");
            System.out.println("  4. 停止导航");
            System.out.println("  5. 返回主菜单");
            System.out.print("  请输入操作选项 (1-5): ");
            if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); continue; }
            int choice = scanner.nextInt();
            scanner.nextLine(); 
            
            String machineId;
            PathPlan plan;
            switch (choice) {
                case 1:
                    System.out.println("    可选策略: 1. A*算法, 2. 最短路径, 3. 能源优化");
                    System.out.print("    请选择新策略 (1-3): ");
                    if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); continue; }
                    int strategyChoice = scanner.nextInt(); scanner.nextLine();
                    if (strategyChoice == 1) controlPanel.setPathPlanningStrategy(new AStarPathStrategy());
                    else if (strategyChoice == 2) controlPanel.setPathPlanningStrategy(new ShortestPathStrategy());
                    else if (strategyChoice == 3) controlPanel.setPathPlanningStrategy(new EnergyEfficientPathStrategy());
                    else System.out.println("无效策略选项。");
                    break;
                case 2:
                    controlPanel.displayAllMachineStatus();
                    System.out.print("  请输入要规划路径的农机ID: "); machineId = scanner.nextLine();
                    System.out.print("  请输入起点X坐标: "); double sx = scanner.nextDouble();
                    System.out.print("  请输入起点Y坐标: "); double sy = scanner.nextDouble();
                    System.out.print("  请输入终点X坐标: "); double ex = scanner.nextDouble();
                    System.out.print("  请输入终点Y坐标: "); double ey = scanner.nextDouble(); scanner.nextLine();
                    // 简化障碍物输入，实际应用中可能从地图或传感器获取
                    System.out.print("  是否有障碍物? (y/n): ");
                    double[][] obstacles = null;
                    if (scanner.nextLine().equalsIgnoreCase("y")) {
                        System.out.print("  请输入障碍物数量: "); int obsCount = scanner.nextInt(); scanner.nextLine();
                        obstacles = new double[obsCount][2];
                        for (int i = 0; i < obsCount; i++) {
                            System.out.print("  请输入障碍物 " + (i+1) + " X坐标: "); obstacles[i][0] = scanner.nextDouble();
                            System.out.print("  请输入障碍物 " + (i+1) + " Y坐标: "); obstacles[i][1] = scanner.nextDouble(); scanner.nextLine();
                        }
                    }
                    controlPanel.planPathForMachine(machineId, sx, sy, ex, ey, obstacles);
                    break;
                case 3:
                    System.out.print("  请输入要启动导航的农机ID: "); machineId = scanner.nextLine();
                    // 假设使用最近一次为该农机规划的路径，或让用户选择路径
                    // 这里简化为使用导航系统当前的路径（如果已规划）
                    plan = controlPanel.getNavigationSystem().getCurrentPath(); 
                    if (plan == null) {
                         System.out.println("  请先为农机规划路径。");
                         // 或者可以提示用户立即规划
                         // PathPlan newPlan = controlPanel.planPathForMachine(...) 
                         // controlPanel.startNavigationForMachine(machineId, newPlan);
                         break;
                    }
                    controlPanel.startNavigationForMachine(machineId, plan);
                    break;
                case 4:
                    System.out.print("  请输入要停止导航的农机ID (通常是当前导航的农机): "); machineId = scanner.nextLine();
                    controlPanel.stopNavigationForMachine(machineId);
                    break;
                case 5:
                    back = true;
                    break;
                default:
                    System.out.println("  无效选项。");
            }
        }
    }

    private static void demoCommandPattern(Scanner scanner, ControlPanelFacade controlPanel) {
        System.out.println("\n  --- 命令模式演示 (农机启动/停止与撤销) ---");
        controlPanel.displayAllMachineStatus();
        System.out.print("  请输入要操作的农机ID: ");
        String machineId = scanner.nextLine();
        AgriculturalMachine machine = controlPanel.findMachineById(machineId);

        if (machine == null) {
            System.out.println("  未找到农机 " + machineId);
            return;
        }

        RemoteControl rc = controlPanel.getRemoteControl(); // 获取外观类中的遥控器实例

        System.out.println("  1. 启动农机");
        System.out.println("  2. 停止农机");
        System.out.println("  3. 撤销上一个操作");
        System.out.println("  4. 查看命令历史 (最近3条)");
        System.out.print("  请选择操作 (1-4): ");
        if (!scanner.hasNextInt()) { System.out.println("无效输入。"); scanner.next(); return; }
        int choice = scanner.nextInt();
        scanner.nextLine();

        switch (choice) {
            case 1:
                rc.setCommand(new StartMachineCommand(machine));
                rc.pressButton();
                break;
            case 2:
                rc.setCommand(new StopMachineCommand(machine));
                rc.pressButton();
                break;
            case 3:
                rc.pressUndoButton();
                break;
            case 4:
                rc.viewCommandHistory(3);
                break;
            default:
                System.out.println("  无效命令操作。");
        }
        System.out.println("  操作后农机 "+machine.getId()+" 状态: " + machine.getStatus());
    }
}